using System;
namespace GameServer.Common.Utils
{
    /*
     * A collection of static methods for common math operations.
    */



    public class Math2
    {


        // Converts radians to degrees
        public static double ToDeg(double rad)
        {
            return rad / Math.PI * 180;
        }

        // Converts degrees to radians
        public static double ToRad(double deg)
        {
            return deg / 180.0 * Math.PI;
        }

        /// <summary>
        /// Returns a random number between 0.0 and the passed max value
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        public static double RandDouble(Random random, double max)
        {
            return random.NextDouble() * max;
        }

        /// <summary>
        /// Returns a random double within the range.
        /// </summary>
        /// <param name="min">Minimum value</param>
        /// <param name="max">Maximum value</param>
        /// <returns></returns>
        public static double RandDouble(Random random, double min, double max)
        {
            if (max < min)
            {
                double tmpVal = max;
                max = min;
                min = max;
            }
            return random.NextDouble() * (max - min) + min;
        }

        /// <summary>
        /// 50% chance of returning true.
        /// </summary>
        /// <returns></returns>
        public static bool Chance(Random random)
        {
            return Chance(random, 0.5);
        }

        /// <summary>
        /// Returns true or false based on chance
        /// </summary>
        /// <param name="chance">Probability that the function returns true. Values: 0.0 to 1.0</param>
        /// <returns></returns>
        public static bool Chance(Random random, double chance)
        {
            return (random.NextDouble() < chance) ? true : false;
        }


        public static double GetAngleOfElevationDegree(double fromX, double fromY, double toX, double toY)
        {
            double returnAngle = Math.Atan2(toY - fromY, toX - fromX) / Math.PI * 180;
            returnAngle = ConvertTo180DegreeAngle(returnAngle);
            return returnAngle;
        }


        public static double ConvertTo180DegreeAngle(double angle360)
        {
            angle360 = NormalizeAngle360(angle360);
            if (angle360 > 180)
                angle360 = angle360 - 360;
            return angle360;
        }

        public static double NormalizeAngle360(double angle360)
        {
            while (angle360 >= 360)
                angle360 = angle360 % 360;
            return angle360;
        }

        //        public static double getChangeInAngle(toAngle180:Number, fromAngle180 : Number, radians : Boolean = false){
        //            double returnAngle ;
        //            returnAngle = toAngle180 - fromAngle180;
        //            if(!radians){
        //                if(returnAngle > 180)
        //                    returnAngle = returnAngle - 360;
        //                else
        //                    if(returnAngle < -180)
        //                        returnAngle = 360 - returnAngle;
        ////				while(returnAngle >= 360 || returnAngle <= -360)
        ////					returnAngle = returnAngle % 360;
        //            }
        //            else{
        //                throw new Error("not implemented");
        //            }
        //            return returnAngle;
        //        }

        public static double ConvertTo360DegreeAngle(double angle180)
        {
            if (angle180 < 0)
            {
                angle180 += 360;
            }
            return angle180;
        }

        public static double GetDistance(double x1, double y1, double x2, double y2)
        {
            return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        }

        /// <summary>
        /// Gets the number of degrees that separate two angles. Measures the smaller difference.
        /// </summary>
        /// <param name="toAngle180"></param>
        /// <param name="fromAngle180">Whether the difference will be positive or negative will be with respect to this angle.</param>
        /// <returns></returns>
        public static double GetChangeInAngle(double toAngle180, double fromAngle180)
        {
            return GetChangeInAngle(toAngle180, fromAngle180, false);
        }


        /// <summary>
        /// Gets the number of degrees or radians that separate two angles. Measures the smaller difference.
        /// </summary>
        /// <param name="toAngle180"></param>
        /// <param name="fromAngle180">Whether the difference will be positive or negative will be with respect to this angle.</param>
        /// <param name="radians">If set to true will return the value in radians.</param>
        /// <returns></returns>
        
        public static double GetChangeInAngle(double toAngle180, double fromAngle180, bool radians){
			double returnAngle;
			returnAngle = toAngle180 - fromAngle180;
			if(!radians){
				if(returnAngle > 180)
					returnAngle = returnAngle - 360;
				else
					if(returnAngle < -180)
						returnAngle = 360 - returnAngle;
			}
			else{
				throw new Exception("not implemented");
			}
			return returnAngle;
		}
    }
}
